#include "lib7ziparchivehandler.h"

Lib7zipArchiveHandler::Lib7zipArchiveHandler(QObject *parent)
    : QObject(parent)
{
    mImageCache = new QCache<int, QByteArray>(6);
    if (!mLib7zip.Initialize()) qDebug() << "Failed to initialise lib7zip.";
}

Lib7zipArchiveHandler::~Lib7zipArchiveHandler()
{
    if (!mWorkingFilePath.isEmpty())
    {
        delete mInStream;
        delete mArchive;
    }
    delete mImageCache;
}

void Lib7zipArchiveHandler::closeWorkingArchive()
{
    if (mWorkingFilePath.isEmpty()) return;
    delete mInStream;
    delete mArchive;
    mImageCache->clear();
    mWorkingFilePath.clear();
}

QString Lib7zipArchiveHandler::workingFilePath()
{
    return mWorkingFilePath;
}

QByteArray* Lib7zipArchiveHandler::dataAt(int index)
{
    QMutexLocker locker(&archiveReaderMutex);
    QByteArray *qba = mImageCache->object(index);
    if (qba) return qba;
    ArchiveQByteArrayStream ostream;
    if (!mArchive->Extract(static_cast<unsigned int>(index), &ostream)) return new QByteArray;
    qba = ostream.byteArray();
    mImageCache->insert(index, qba, 1);
    return qba;
}

QStandardItemModel *Lib7zipArchiveHandler::openArchiveFile(const QString &path)
{
    QMutexLocker locker(&archiveReaderMutex);
    this->closeWorkingArchive();
    mInStream = new ArchiveInStream(path);
    if (!mLib7zip.OpenArchive(mInStream, &mArchive, true)) return new QStandardItemModel;

    QStandardItemModel *itemModel = new QStandardItemModel;
    QStandardItem *headerItem = new QStandardItem(QFileInfo(path).fileName());
    headerItem->setData(path, Qt::UserRole);
    itemModel->setHorizontalHeaderItem(0, headerItem);
    unsigned int itemcount = 0;
    mArchive->GetItemCount(&itemcount);
    for (unsigned int i=0; i<itemcount; ++i)
    {
        C7ZipArchiveItem *archiveItem;
        if (!mArchive->GetItemInfo(i, &archiveItem)) return new QStandardItemModel();
        if (archiveItem->IsDir()) continue; // ignore directories
        QString filepath = QString::fromStdWString(archiveItem->GetFullPath());
        if (!Utils::isImage(QFileInfo(filepath).suffix())) continue; // or files that aren't images
        QStandardItem *item = new QStandardItem(filepath);
        QVariant position(archiveItem->GetArchiveIndex());
        item->setData(position, Qt::UserRole);
        item->setEditable(false);
        itemModel->appendRow(item);
    }
    mWorkingFilePath = path;
    return itemModel;
}
